package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.Category;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: YHL
 * @time: 2021/2/24 19:59
 */
@Service
public class GoodsServiceImpl implements GoodsService {
    @Autowired
    private SpuService spuService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private SpuDetailService spuDetailService;
    @Autowired
    private SpecParamService paramService;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Override
    public PageDTO<SpuDTO> pageQuery(Integer page, Integer rows, Long id, Long cid, Long bid, Boolean saleable) {
        IPage<Spu> iPage = new Page<>(page, rows);
        //查询结果不用自己接收，已经被封装到参数iPage
        this.spuService.page(iPage, new QueryWrapper<Spu>()
                .eq(null != id, "id", id)
                .eq(null != cid, "cid3", cid)
                .eq(null != bid, "brand_id", bid)
                .eq(null != saleable, "saleable", saleable)
        );
        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(iPage.getRecords());
        spuDTOS.forEach(spuDTO -> {
            //TODO 分类和品牌查询要优化，建议加入缓存减少数据库访问
            //分类名称以及品牌名称
            //根据分类id集合查询到分类集合然后从集合中取出分类的名称，并且拼接为字符串使用"/"作为分隔符
            String names = this.categoryService.listByIds(spuDTO.getCategoryIds()).stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);
            spuDTO.setBrandName(this.brandService.getById(spuDTO.getBrandId()).getName());
        });
        return new PageDTO<>(iPage.getTotal(), iPage.getPages(), spuDTOS);
    }

    @Override
    public void modifySaleable(Long id, Boolean saleable) {
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        //update tb_spu set saleable = #{saleable} where id = #{id}
        this.spuService.updateById(spu);


        Sku sku = new Sku();
        sku.setSaleable(saleable);
        //update tb_sku set saleable = #{saleable} where spu_id = #{id}
        this.skuService.update(sku,new QueryWrapper<Sku>().eq("spu_id",id));
        String routingKey =saleable?"item.up":"item.down";
        this.amqpTemplate.convertAndSend("yhl",routingKey,id);
    }

    @Override
    @Transactional
    public void addGoods(SpuDTO spuDTO) {
        //分析，数据是否是合理的
        Spu spu = spuDTO.toEntity(Spu.class);
        this.spuService.save(spu);
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spu.getId());
        this.spuDetailService.save(spuDetail);
        List<Sku> skuList = spuDTO
                .getSkus()
                .stream()
                .map(skuDTO -> {
                    Sku sku = skuDTO.toEntity(Sku.class);
                    sku.setSpuId(spu.getId());
                    return sku;
                })
                .collect(Collectors.toList());
        this.skuService.saveBatch(skuList);
    }

    @Override
    public SpuDTO queryGoodsById(Long id) {
//        spu的全部
        PageDTO<SpuDTO> spuDTOPageDTO = this.pageQuery(1, 1, id, null, null, null);
        if (null!=spuDTOPageDTO && !CollectionUtils.isEmpty(spuDTOPageDTO.getItems())){
//                获取到spuDto

            SpuDTO spuDTO = spuDTOPageDTO.getItems().get(0);
//            添加detail
            spuDTO.setSpuDetail(new SpuDetailDTO(this.spuDetailService.getById(id)));
//            添加sku
            spuDTO.setSkus(SkuDTO.convertEntityList(this.skuService.query().eq("spu_id",id).list()));

                return spuDTO;
        }

  throw new LyException(400,"请求id有误");
    }

    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        //id不为空说明spu有修改需求
        if (null != spuDTO.getId()) {
            Spu spu = spuDTO.toEntity(Spu.class);
            this.spuService.updateById(spu);
        }
        // detail不为空说明detail有修改需求 ,
        if (null != spuDTO.getSpuDetail()) {
            this.spuDetailService.updateById(spuDTO.getSpuDetail().toEntity(SpuDetail.class));
        }
        //说明sku有修改需求
        if (!CollectionUtils.isEmpty(spuDTO.getSkus())) {
//            //三个集合
//            List<Sku> toBeAdd = new ArrayList<>();
//            List<Sku> toBeDelete = new ArrayList<>();
//            List<Sku> toBeUpdate = new ArrayList<>();
//            spuDTO.getSkus().forEach(skuDTO -> {
//                Sku sku = skuDTO.toEntity(Sku.class);
//                //如果id为空表示是要新增的
//                if (sku.getId() == null) {
//                    toBeAdd.add(sku);
//                } else if (sku.getSaleable() == false) {
//                    toBeDelete.add(sku);
//                }else {
//                    toBeUpdate.add(sku);
//                }
//            });
            //sku只有两个键值对，key为true表示，表示要新增或修改，false，表示要删除
            Map<Boolean, List<Sku>> skuMap = spuDTO.getSkus().stream().map(skuDTO -> skuDTO.toEntity(Sku.class)).collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));
            //两个集合
            //批量新增或修改
            if (!CollectionUtils.isEmpty(skuMap.get(true))) {
                this.skuService.saveOrUpdateBatch(skuMap.get(true));
            }
            //批量删除
            if (!CollectionUtils.isEmpty(skuMap.get(false))) {
                this.skuService.removeByIds(skuMap.get(false).stream().map(Sku::getId).collect(Collectors.toList()));
            }
        }
    }

    @Override
    public SpuDetailDTO querySpuDetailById(Long id) {
        return new SpuDetailDTO(this.spuDetailService.getById(id));
    }

    @Override
    public List<SkuDTO> listSkuBySpuID(Long spuId) {
        //select * from tb_sku where spu_id = #{spuId}
        return  SkuDTO.convertEntityList(this.skuService.query().eq("spu_id",spuId).list());
    }

    @Override
    public SpuDTO querySpuById(Long id) {
        return new SpuDTO(this.spuService.getById(id));
    }

    @Override
    public List<SpecParamDTO> listSpecParam(Long id, Boolean searching) {
        Spu spu = this.spuService.getById(id);
        //根据商品id查询到对应的分类，根据分类获取到当前分类下所有的商品规格参数
        List<SpecParamDTO> specParamDTOS = this.paramService.listSpecParm(null, spu.getCid3(),searching);
        //需要给每一个规格参数赋值，规格参数的值，存在了spuDetail中的specification中
        String specJson = this.spuDetailService.getById(id).getSpecification();
        //从spuDetail中获取到规格属性的key以及对应的值，并且转换为map，map的key就是规格参数的id
        Map<Long, Object> paramMap = JsonUtils.nativeRead(specJson, new TypeReference<Map<Long, Object>>() {
        });
        //循环specParam给每个对象的value赋值
        specParamDTOS.forEach(specParamDTO -> specParamDTO.setValue(paramMap.get(specParamDTO.getId())));
        return specParamDTOS;
    }


}

